#![allow(unused_imports, unused_qualifications, unused_extern_crates)]
extern crate chrono;
extern crate uuid;

{{#usesXml}}use serde_xml_rs;{{/usesXml}}
use serde::ser::Serializer;

use std::collections::HashMap;
use models;
use swagger;

{{#models}}{{#model}}
{{#description}}/// {{{description}}}
{{/description}}{{#isEnum}}/// Enumeration of values.
/// Since this enum's variants do not hold data, we can easily define them them as `#[repr(C)]`
/// which helps with FFI.
#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize, Eq, Ord)]{{#xmlName}}
#[serde(rename = "{{xmlName}}")]{{/xmlName}}
pub enum {{classname}} { {{#allowableValues}}{{#enumVars}}
    #[serde(rename = {{{value}}})]
    {{name}},{{/enumVars}}{{/allowableValues}}
}

impl ::std::fmt::Display for {{classname}} {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self { {{#allowableValues}}{{#enumVars}}
            {{classname}}::{{name}} => write!(f, "{}", {{{value}}}),{{/enumVars}}{{/allowableValues}}
        }
    }
}

impl ::std::str::FromStr for {{classname}} {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
{{#allowableValues}}{{#enumVars}}            {{{value}}} => Ok({{classname}}::{{name}}),
{{/enumVars}}{{/allowableValues}}            _ => Err(()),
        }
    }
}
{{/isEnum}}{{^isEnum}}{{#dataType}}{{! newtype}}#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
{{#xmlName}}#[serde(rename = "{{xmlName}}")]{{/xmlName}}
pub struct {{classname}}({{{dataType}}});

impl ::std::convert::From<{{dataType}}> for {{classname}} {
    fn from(x: {{dataType}}) -> Self {
        {{classname}}(x)
    }
}

impl ::std::convert::From<{{classname}}> for {{dataType}} {
    fn from(x: {{classname}}) -> Self {
        x.0
    }
}

impl ::std::ops::Deref for {{classname}} {
    type Target = {{{dataType}}};
    fn deref(&self) -> &{{{dataType}}} {
        &self.0
    }
}

impl ::std::ops::DerefMut for {{classname}} {
    fn deref_mut(&mut self) -> &mut {{{dataType}}} {
        &mut self.0
    }
}

{{/dataType}}{{^dataType}}{{#arrayModelType}}{{#vendorExtensions}}{{#itemXmlName}}// Utility function for wrapping list elements when serializing xml
fn wrap_in_{{itemXmlName}}<S>(item: &Vec<{{arrayModelType}}>, serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    serde_xml_rs::wrap_primitives(item, serializer, "{{itemXmlName}}")
}

{{/itemXmlName}}{{/vendorExtensions}}{{! vec}}#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct {{classname}}(Vec<{{{arrayModelType}}}>);

impl ::std::convert::From<Vec<{{arrayModelType}}>> for {{classname}} {
    fn from(x: Vec<{{arrayModelType}}>) -> Self {
        {{classname}}(x)
    }
}

impl ::std::convert::From<{{classname}}> for Vec<{{arrayModelType}}> {
    fn from(x: {{classname}}) -> Self {
        x.0
    }
}

impl ::std::iter::FromIterator<{{arrayModelType}}> for {{classname}} {
    fn from_iter<U: IntoIterator<Item={{arrayModelType}}>>(u: U) -> Self {
        {{classname}}(Vec::<{{arrayModelType}}>::from_iter(u))
    }
}

impl ::std::iter::IntoIterator for {{classname}} {
    type Item = {{arrayModelType}};
    type IntoIter = ::std::vec::IntoIter<{{arrayModelType}}>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}

impl<'a> ::std::iter::IntoIterator for &'a {{classname}} {
    type Item = &'a {{arrayModelType}};
    type IntoIter = ::std::slice::Iter<'a, {{arrayModelType}}>;

    fn into_iter(self) -> Self::IntoIter {
        (&self.0).into_iter()
    }
}

impl<'a> ::std::iter::IntoIterator for &'a mut {{classname}} {
    type Item = &'a mut {{arrayModelType}};
    type IntoIter = ::std::slice::IterMut<'a, {{arrayModelType}}>;

    fn into_iter(self) -> Self::IntoIter {
        (&mut self.0).into_iter()
    }
}

impl ::std::ops::Deref for {{classname}} {
    type Target = Vec<{{{arrayModelType}}}>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl ::std::ops::DerefMut for {{classname}} {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

{{/arrayModelType}}{{^arrayModelType}}{{! general struct}}#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]{{#xmlName}}
#[serde(rename = "{{xmlName}}")]{{/xmlName}}
pub struct {{classname}} {
{{#vars}}{{#description}}    /// {{{description}}}
{{/description}}{{#isEnum}}    // Note: inline enums are not fully supported by swagger-codegen
{{/isEnum}}    #[serde(rename = "{{baseName}}")]{{#vendorExtensions}}{{#itemXmlName}}
    #[serde(serialize_with = "wrap_in_{{itemXmlName}}")]{{/itemXmlName}}{{/vendorExtensions}}{{#required}}
    pub {{name}}: {{#vendorExtensions}}{{#x-nullable}}swagger::Nullable<{{/x-nullable}}{{/vendorExtensions}}{{{datatype}}}{{#vendorExtensions}}{{#x-nullable}}>{{/x-nullable}}{{/vendorExtensions}},
{{/required}}{{^required}}{{#vendorExtensions}}{{#x-nullable}}    #[serde(deserialize_with = "swagger::nullable_format::deserialize_optional_nullable")]
    #[serde(default = "swagger::nullable_format::default_optional_nullable")]
{{/x-nullable}}{{/vendorExtensions}}
    #[serde(skip_serializing_if="Option::is_none")]
    pub {{name}}: Option<{{#vendorExtensions}}{{#x-nullable}}swagger::Nullable<{{/x-nullable}}{{/vendorExtensions}}{{#isListContainer}}Vec<{{#items}}{{{datatype}}}{{/items}}>{{/isListContainer}}{{^isListContainer}}{{{datatype}}}{{/isListContainer}}{{#vendorExtensions}}{{#x-nullable}}>{{/x-nullable}}{{/vendorExtensions}}>,
{{/required}}

{{/vars}}
}

impl {{classname}} {
    pub fn new({{#vars}}{{^defaultValue}}{{name}}: {{#vendorExtensions}}{{#x-nullable}}swagger::Nullable<{{/x-nullable}}{{/vendorExtensions}}{{{datatype}}}{{#vendorExtensions}}{{#x-nullable}}>{{/x-nullable}}{{/vendorExtensions}}, {{/defaultValue}}{{/vars}}) -> {{classname}} {
        {{classname}} {
{{#vars}}            {{name}}: {{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}{{name}}{{/defaultValue}},
{{/vars}}
        }
    }
}
{{/arrayModelType}}{{/dataType}}{{/isEnum}}{{/model}}{{/models}}{{#usesXmlNamespaces}}
//XML namespaces
pub mod namespaces {
    lazy_static!{
        {{#models}}{{#model}}{{#xmlNamespace}}pub static ref {{#vendorExtensions}}{{upperCaseName}}{{/vendorExtensions}}: String = "{{xmlNamespace}}".to_string();
        {{/xmlNamespace}}{{/model}}{{/models}}
    }
}
{{/usesXmlNamespaces}}
